﻿#region License
/*
Copyright (c) 2005-2011, CellAO Team

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
    * Neither the name of the CellAO Team nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#endregion

#region Usings...
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Data;
using System.Text;
using AO.Core;
using Cell.Core;
using ZoneEngine.Misc;
using ZoneEngine.Packets;
using ZoneEngine.Database;
using System.Globalization;
#endregion

namespace ZoneEngine.PacketHandlers
{
    /// <summary>
    /// 
    /// </summary>

    public class ChatCmd
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="packet"></param>
        /// <param name="client"></param>
        public static void Read(ref byte[] packet, Client client)
        {
            #region Bytes / Strings / Ints  setup

            PacketReader reader = new PacketReader(ref packet);
            var _header = reader.PopHeader();
            reader.PopByte();
            int unknown = reader.PopInt();
            Identity target = reader.PopIdentity();
            int cmdLength = reader.PopInt();
            string fullArgs = reader.PopString(cmdLength).TrimEnd(char.MinValue);
            string temp = "";
            do
            {
                temp = fullArgs;
                fullArgs = fullArgs.Replace("  ", " ");
            } while (temp != fullArgs);

            string[] cmdArgs = fullArgs.Trim().Split(' ');
            reader.Finish();

            Client mClient;
            string response;
            int statId;

            #endregion

            switch (cmdArgs[0].ToLower())
            {
                #region /command bank
                case "bank":
                    Packets.BankOpen.Send(client);
                    break;
                #endregion
                #region /npc
                case "npc":		//pass npc commands to the NPCHandler
                    {
                        if (cmdArgs.Length < 2)
                            break;
                        NPC.NPCHandler.NPCCmd(ref cmdArgs, target);
                    }
                    break;
                #endregion
                #region /command effect
                case "effect":
                    {
                        if (cmdArgs.Length == 4)
                        {
                            if ((cmdArgs[1] == "GfxEffect") && (cmdArgs[2] == "Value"))
                            {
                                int gfx = 0;
                                try
                                {
                                    gfx = int.Parse(cmdArgs[3]);
                                }
                                catch (FormatException)
                                {
                                    break;
                                }
                                //begin assembling packet here
                                PacketWriter pout = new PacketWriter();
                                pout.PushByte(0xDF); pout.PushByte(0xDF);
                                pout.PushShort(10);
                                pout.PushShort(1);
                                pout.PushShort(0);
                                pout.PushInt(3086);
                                pout.PushInt(client.Character.ID);
                                pout.PushInt(0x4D450114);
                                pout.PushIdentity(target);
                                pout.PushByte(0);
                                pout.Push3F1Count(1);           // effects count
                                // effect starts
                                pout.PushIdentity(53030, 0);    // effect ID (53030 = GfxEffect)
                                pout.PushInt(4);                // ?
                                pout.PushInt(0);                // Criterion count
                                pout.PushInt(1);                // Hits
                                pout.PushInt(0);                // Delay
                                pout.PushInt(0);                // 
                                pout.PushInt(0);                // 
                                // effect args
                                pout.PushInt(gfx);              // Value
                                pout.PushInt(0);                // GfxLife
                                pout.PushInt(0);                // GfxSize
                                pout.PushInt(0);                // GfxRed
                                pout.PushInt(0);                // GfxGreen
                                pout.PushInt(0);                // GfxBlue
                                pout.PushInt(0);                // GfxFade
                                // effect args end
                                // effect ends
                                pout.PushIdentity(50000, client.Character.ID);
                                byte[] reply = pout.Finish();
                                //done creating the packet
                                Misc.Announce.Playfield(client.Character.PlayField, ref reply);
                            }
                        }
                    }
                    break;
                #endregion
                #region /set command
                case "set":
                    if (client.Character.Stats.GmLevel.Value == 0) // 215 = GMLevel
                    {
                        client.SendChatText("You are not authorized to use this command.");
                        break;
                    }

                    if (cmdArgs.Length != 3)
                    {
                        client.SendChatText("Usage: /set &lt;stat&gt; &lt;value&gt;");
                        client.SendChatText("where stat is stat number or name");
                        break;
                    }

                    if (target.Instance == 0)
                    {
                        client.SendChatText("Unable to find target.");
                        break;
                    }

                    statId = StatsList.GetStatId(cmdArgs[1]);
                    if (statId == 1234567890)
                    {
                        client.SendChatText("Unknown Stat name " + cmdArgs[1]);
                        break;
                    }
                    uint statNewValue = 1234567890;
                    try
                    {
                        statNewValue = uint.Parse(cmdArgs[2]);
                    }
                    catch
                    {
                        try
                        {
                            // For values >= 2^31
                            statNewValue = (uint.Parse(cmdArgs[2]));
                        }
                        catch { }
                    }
                    Character tempch = (Character)Misc.FindDynel.FindDynelByID(target.Type, target.Instance);
                    uint statOldValue;
                    try
                    {
                        statOldValue = (uint)tempch.Stats.GetBaseValue(statId);
                        tempch.Stats.Set(statId, statNewValue);
                        if (tempch.client != null)
                        {
                            tempch.Stats.Send(tempch.client, statId);
                        }
                    }
                    catch
                    {
                        client.SendChatText("Unknown StatId " + statId);
                        break;
                    }

                    response = "Character " + target.Instance + ": Stat " + StatsList.GetStatName(statId) + " (" + statId + ") =";

                    response += " New: " + statNewValue;

                    response += " Old: " + statOldValue;

                    client.SendChatText(response);

                    break;
                #endregion
                #region /get command
                case "get":
                    if (cmdArgs.Length != 2)
                    {
                        client.SendChatText("Usage: /get &lt;stat&gt;");
                        client.SendChatText("where stat is stat number or name");
                        break;
                    }
                    if (target.Type != 50000)
                    {
                        client.SendChatText("Target must be player/monster/NPC");
                        break;
                    }

                    Dynel dyn;
                    dyn = Misc.FindDynel.FindDynelByID(target.Type, target.Instance);
                    if (dyn != null)
                    {
                        Character ch = (Character)dyn;
                        //ch.CalculateSkills();  // May be obsolete in the future
                        statId = StatsList.GetStatId(cmdArgs[1]);
                        if (statId == 1234567890)
                        {
                            client.SendChatText("Unknown Stat name " + cmdArgs[1]);
                            break;
                        }

                        uint statValue;
                        int effectiveValue;
                        int trickle;
                        int mod;
                        int perc;
                        try
                        {
                            statValue = ch.Stats.GetBaseValue(statId);
                            effectiveValue = ch.Stats.Get(statId);
                            trickle = ch.Stats.GetStatbyNumber(statId).Trickle;
                            mod = ch.Stats.GetStatbyNumber(statId).StatModifier;
                            perc = ch.Stats.GetStatbyNumber(statId).StatPercentageModifier;
                        }
                        catch
                        {
                            client.SendChatText("Unknown Stat Id " + statId);
                            break;
                        }

                        response = "Character " + ch.Name + " (" + ch.ID + "): Stat " + StatsList.GetStatName(statId) + " (" + statId + ") = " + statValue;

                        client.SendChatText(response);
                        if (statValue != ch.Stats.Get(cmdArgs[1]))
                        {
                            response = "Effective value Stat " + StatsList.GetStatName(statId) + " (" + statId + ") = " + effectiveValue;
                            client.SendChatText(response);
                        }
                        response = "Trickle: " + trickle + " Modificator: " + mod + " Percentage: " + perc;
                        client.SendChatText(response);

                    }
                    else
                    {
                        client.SendChatText("Unable to find target.");
                    }
                    break;
                #endregion
                #region /command coorddebug
                case "coorddebug":
                    client.SendChatText(client.Character.Coordinates + " " + client.Character.PlayField + " " + client.Character.Heading.x.ToString() + " " + client.Character.Heading.y.ToString() + " " + client.Character.Heading.z.ToString() + " " + client.Character.Heading.w.ToString() + " " + client.Character.Heading.VectorRepresentation().ToString());
                    break;
                #endregion
                #region /teleport command
                case "tp":
                case "teleport":
                case "teleportdynel":
                    if (cmdArgs.Length < 3)
                    {
                        /* Msg 110:13065464 = "Invalid length." */
                        client.SendFeedback(110, 13065464);
                        break;
                    }
                    try
                    {
                        AOCoord coord;
                        int PF, i = 1;

                        coord = new AOCoord(float.Parse(cmdArgs[i++], System.Globalization.CultureInfo.InvariantCulture), client.Character.Coordinates.y, float.Parse(cmdArgs[i++], System.Globalization.CultureInfo.InvariantCulture));

                        if ((cmdArgs.Length > i) && (cmdArgs[i].ToLower() == "y"))
                        {
                            i++;
                            coord.y = float.Parse(cmdArgs[i++], System.Globalization.CultureInfo.InvariantCulture);
                        }

                        if ((cmdArgs.Length > i) && (int.TryParse(cmdArgs[i], out PF)))
                        {
                            PF = int.Parse(cmdArgs[i++], System.Globalization.CultureInfo.InvariantCulture);
                        }
                        else
                        {
                            PF = client.Character.PlayField;
                        }

                        if (cmdArgs[0].ToLower() == "teleportdynel")
                        {
                            if (!FindClient.FindClientByID(target.Instance, out mClient))
                            { Console.WriteLine("Target not found"); break; }

                            if (!Playfields.ValidPlayfield(PF))
                            { client.SendFeedback(110, 188845972); break; }
                            mClient.Teleport(coord, mClient.Character.Heading, PF);
                        }
                        else
                        {
                            if (!Playfields.ValidPlayfield(PF))
                            { client.SendFeedback(110, 188845972); break; }
                            client.Teleport(coord, client.Character.Heading, PF);
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Error: " + e);
                    }
                    break;
                #endregion
                #region /command assist
                case "assist":
                    if (cmdArgs.Length != 2)
                    {
                        client.SendChatText("Usage: /command assist &lt;name&gt;");
                        break;
                    }
                    if (FindClient.FindClientByName(cmdArgs[1], out mClient))
                    {
                        client.Teleport(mClient.Character.Coordinates, mClient.Character.Heading, mClient.Character.PlayField);
                        break;
                    }
                    break;
                #endregion
                #region /command summon
                case "summon":
                    if (cmdArgs.Length != 2)
                    {
                        client.SendChatText("Usage: /command summon &lt;name&gt;");
                        break;
                    }
                    if (FindClient.FindClientByName(cmdArgs[1], out mClient))
                    {
                        mClient.Teleport(client.Character.Coordinates, client.Character.Heading, client.Character.PlayField);
                        break;
                    }
                    break;
                #endregion
                #region /command ghost
                case "ghost":
                    if (cmdArgs.Length != 2)
                    {
                        client.SendChatText("Usage: /command ghost &lt;name&gt;");
                        break;
                    }
                    if (FindClient.FindClientByName(cmdArgs[1], out mClient))
                    {
                        mClient.Server.DisconnectClient(mClient);
                        break;
                    }
                    break;
                #endregion
                #region /command removename
                case "removename":
                    {
                        if (cmdArgs.Length != 1)
                        {
                            client.SendChatText("Usage: /command removename");
                            break;
                        }
                        if (target.Type != 50000)
                        {
                            client.SendChatText("Target must be player");
                            break;
                        }
                        if (FindClient.FindClientByID(target.Instance, out mClient))
                        {
                            mClient.Character.LastName = "";
                            mClient.Character.FirstName = "";
                            mClient.Character.WriteNames();
                            client.SendChatText(mClient.Character.Name + "'s names have been reset.");
                            break;
                        }
                        client.SendChatText("Unable to find target.");
                        break;
                    }
                #endregion
                #region /command setname
                case "name":
                case "setname":
                    if (cmdArgs.Length < 3)
                    {
                        client.SendChatText("Usage: /command setname &lt;first/last/nick&gt; &lt;newname&gt;");
                        break;
                    }

                    if (target.Type != 50000)
                    {
                        client.SendChatText("Target must be player");
                        break;
                    }

                    string newName = fullArgs.Substring(cmdArgs[0].Length + 1 + cmdArgs[1].Length + 1);

                    if (FindClient.FindClientByID(target.Instance, out mClient))
                    {
                        switch (cmdArgs[1].ToLower())
                        {
                            case "first":
                            case "firstname":
                                if (newName == "\"\"")
                                    newName = "";
                                client.SendChatText(mClient.Character.Name + "'s first name has been set to " + newName);
                                mClient.Character.FirstName = newName;
                                mClient.Character.WriteNames();
                                break;
                            case "last":
                            case "lastname":
                                if (newName == "\"\"")
                                    newName = "";
                                client.SendChatText(mClient.Character.Name + "'s last name has been set to " + newName);
                                mClient.Character.LastName = newName;
                                mClient.Character.WriteNames();
                                break;
                            case "nick":
                            case "nickname":
                                if (cmdArgs.Length != 3)
                                {
                                    client.SendChatText("Usage: /command setname &lt;first/last/nick&gt; &lt;newname&gt;");
                                    break;
                                }
                                client.SendChatText(mClient.Character.Name + "'s nick name has been set to " + newName);
                                mClient.Character.Name = newName;
                                mClient.Character.WriteNames();
                                break;
                            default:
                                client.SendChatText("Usage: /command setname &lt;first/last/nick&gt; &lt;newname&gt;");
                                break;
                        }
                        break;
                    }
                    client.SendChatText("Unable to find target.");
                    break;
                #endregion
                #region /command spawn
                case "spawn":
                    {
                        if (cmdArgs.Length != 3)
                        {
                            client.SendChatText("Usage: /spawn &lt;hash&gt; &lt;level&gt;");
                        }
                        else
                        {
                            NPC.NPCHandler.SpawnMonster(client, cmdArgs[1], uint.Parse(cmdArgs[2]));
                        }
                    }
                    break;
                #endregion
                #region /command shopspawn
                case "shopspawn":
                    {
                        if (cmdArgs.Length != 2)
                        {
                            client.SendChatText("Usage: /command shopspawn &lt;Hash&gt;");
                        }
                        else
                        {
                            NPC.VendorHandler.SpawnVendor(client, cmdArgs[1]);
                        }
                    }
                    break;
                #endregion
                #region /command giveitem
                case "giveitem":
                    if (client.Character.Stats.GmLevel.Value == 0) // 215 = GMLevel
                    {
                        client.SendChatText("You are not authorized to use this command.");
                        break;
                    }
                    if (cmdArgs.Length != 5)
                    {
                        client.SendChatText("Usage: /command giveitem &lt;name&gt; &lt;lowid&gt;  &lt;highid&gt; &lt;QL&gt;");
                        break;
                    }
                    if (FindClient.FindClientByName(cmdArgs[1], out mClient))
                    {
                        int firstfree = 64;
                        firstfree = mClient.Character.GetNextFreeInventory(104);
                        if (firstfree <= 93)
                        {
                            InventoryEntries mi = new InventoryEntries();
                            ItemHandler.Item it = new ItemHandler.Item(Convert.ToInt32(cmdArgs[2]));
                            mi.Placement = firstfree;
                            mi.Container = 104;
                            mi.Item.lowID = Convert.ToInt32(cmdArgs[2]);
                            mi.Item.highID = Convert.ToInt32(cmdArgs[3]);
                            mi.Item.Quality = Convert.ToInt32(cmdArgs[4]);
                            if (it.itemtype != 1)
                            {
                                mi.Item.multiplecount = Math.Max(1, (int)it.getItemAttribute(212));
                            }
                            else
                            {
                                bool found = false;
                                foreach (AOItemAttribute a in mi.Item.Stats)
                                {
                                    if (a.Stat != 212)
                                        continue;
                                    found = true;
                                    a.Value = Math.Max(1, (int)it.getItemAttribute(212));
                                    break;
                                }
                                if (!found)
                                {
                                    AOItemAttribute aoi = new AOItemAttribute();
                                    aoi.Stat = 212;
                                    aoi.Value = Math.Max(1, (int)it.getItemAttribute(212));
                                    mi.Item.Stats.Add(aoi);
                                }
                            }
                            mClient.Character.Inventory.Add(mi);
                            Packets.AddTemplate.Send(mClient, mi);
                        }
                        else
                        {
                            client.SendChatText("Your Inventory is full");
                        }
                    }
                    break;
                #endregion
                #region /command nanoupload
                case "nanoupload":
                    if (client.Character.Stats.GmLevel.Value == 0) // 215 = GMLevel
                    {
                        client.SendChatText("You are not Authorized to use this command.");
                        break;
                    }
                    if (cmdArgs.Length != 3)
                    {
                        client.SendChatText("Usage: /command nanoupload &lt;name&gt; &ltnanoid&gt");
                        break;
                    }
                    if (FindClient.FindClientByName(cmdArgs[1], out mClient))
                    {
                        bool hasNano = (HasNano(Convert.ToInt32(cmdArgs[2]), mClient));
                        if (hasNano == false)
                        {
                            // Old code obsolete, uploaded nanos reside in memory now
                            mClient.Character.UploadNano(Convert.ToInt32(cmdArgs[2]));
                            Packets.UploadNanoupdate.Send(mClient.Character, 53019, Convert.ToInt32(cmdArgs[2]));
                            break;
                        }
                        mClient.SendChatText("The nano already exists in nano programs..");
                        break;
                    }
                    break;
                #endregion
                #region /command remitem
                //Code submitted by Wargreymon from the forums post: http://www.aocell.co/forums/index.php?topic=27.0
                case "delitem":
                case "remitem":
                    if (client.Character.Stats.GmLevel.Value == 0) // 215 = GMLevel
                    {
                        client.SendChatText("You are not authorized to use this command.");
                        break;
                    }
                    if (cmdArgs.Length != 3)
                    {
                        client.SendChatText("Usage: /command remitem &lt;name&gt; &lt;Placement&gt;");
                        break;
                    }
                    if (FindClient.FindClientByName(cmdArgs[1], out mClient))
                    {
                        bool itemExists = (ItemExists(Convert.ToInt32(cmdArgs[2]), mClient));
                        if (itemExists)
                        {
                            Packets.DeleteItem.Send(mClient.Character, 104, Convert.ToInt32(cmdArgs[2]));
                            mClient.Character.Inventory.Remove(mClient.Character.getInventoryAt(Convert.ToInt32(cmdArgs[2])));
                            break;
                        }
                        mClient.SendChatText("There exists no item in the slot you choose");
                        break;
                    }
                    break;
                #endregion
                #region /command online
                case "online":
                    if (client.Character.Stats.GmLevel.Value > 0)
                    {
                        switch (cmdArgs.Length)
                        {
                            //If no input other than /command online then return online for global
                            case 1:
                                foreach (Client name in Program.zoneServer.Clients)
                                {
                                    client.SendChatText(name.Character.Name + " (" + name.Character.PlayField.ToString() + ")");
                                }
                                break;
                            // else 2nd argument will be treated as playfield
                            case 2:
                                int SearchPF;
                                if (int.TryParse(cmdArgs[1], out SearchPF))
                                {
                                    foreach (Client name in Program.zoneServer.Clients)
                                    {
                                        if (client.Character.PlayField == SearchPF)
                                        {
                                            client.SendChatText(name.Character.Name);
                                        }
                                    }
                                }
                                break;
                            default:
                                {
                                    client.SendChatText("ohh no something went wrong");
                                }
                                break;
                        }
                    }
                    break;
                #endregion
                #region /command addwaypoint
                case "addwaypoint":
                    {
                        if ((target.Type != 50000) && (target.Type != 51035)) return;
                        NonPC targetMonster = null;
                        foreach (NonPC mMonster in Program.zoneServer.Monsters)
                        {
                            if (mMonster.ID != target.Instance) continue;
                            targetMonster = mMonster;
                            break;
                        }
                        if (targetMonster == null)
                        {
                            client.SendChatText("Please choose a NPC first");
                            break;
                        }
                        targetMonster.AddWaypoint(client.Character.Coordinates);
                        break;
                    }
                #endregion
                #region addproxydestination
                case "pd":
                    {
                        NumberFormatInfo provider = new NumberFormatInfo();
                        provider.NumberDecimalSeparator = ".";
                        SqlWrapper ms = new SqlWrapper();
                        ms.SqlDelete("DELETE FROM proxydestinations Where playfield=" + client.Character.PlayField);
                        ms.SqlInsert("INSERT INTO proxydestinations VALUES (" + client.Character.PlayField.ToString() + "," + client.Character.Coordinates.x.ToString(provider) + "," + client.Character.Coordinates.y.ToString(provider) + "," + client.Character.Coordinates.z.ToString(provider) +
                            "," + client.Character.Heading.x.ToString(provider) + "," + client.Character.Heading.y.ToString(provider) + "," + client.Character.Heading.z.ToString(provider) + "," + client.Character.Heading.w.ToString(provider) + ");");
                        ms.sqlclose();
                        break;
                    }
                #endregion
                #region /command debugitem <itemid>
                case "debugitem":
                    {
                        bool sendhelp = false;
                        if (cmdArgs.Length == 2)
                        {
                            int itemid;
                            if (Int32.TryParse(cmdArgs[1], out itemid))
                            {
                                ItemHandler.Item it = new ItemHandler.Item(itemid);
                                client.SendChatText("Item Debug Info for Item " + itemid);
                                client.SendChatText("Attack values:");
                                foreach (AOItemAttribute at in it.attack)
                                {
                                    client.SendChatText("Type: " + at.Stat + " Value: " + at.Value);
                                }
                                client.SendChatText("Defense values:");
                                foreach (AOItemAttribute at in it.defend)
                                {
                                    client.SendChatText("Type: " + at.Stat + " Value: " + at.Value);
                                }
                                client.SendChatText("Item Attributes:");
                                foreach (AOItemAttribute at in it.ItemAttributes)
                                {
                                    client.SendChatText("Type: " + at.Stat + " Value: " + at.Value);
                                }

                                client.SendChatText("Events/Functions:");
                                foreach (AOEvents ev in it.ItemEvents)
                                {
                                    client.SendChatText("Eventtype: " + ev.EventType);
                                    foreach (AOFunctions fu in ev.Functions)
                                    {
                                        client.SendChatText("  Functionnumber: " + fu.FunctionType);
                                        foreach (object arg in fu.Arguments)
                                        {
                                            client.SendChatText("    Argument: " + arg);
                                        }
                                    }
                                }
                                break;
                            }
                            else
                                sendhelp = true;
                        }
                        else
                            sendhelp = true;
                        if (sendhelp)
                        {
                            client.SendChatText("Usage: /command debugitem &lgt;itemid&rgt;");
                        }
                        break;
                    }
                #endregion
                #region debugmeshs
                case "debugmeshs":
                    {
                        client.SendChatText("Equipment page:");
                        List<AOMeshs> meshs = client.Character.MeshLayer.GetMeshs();
                        foreach (AOMeshs am in meshs)
                        {
                            int ov = am.OverrideTexture;
                            int me = am.Mesh;
                            int position = am.Position;
                            int layer = am.Layer;
                            client.SendChatText(position + ":" + me + ":" + ov + ":" + layer);
                        }

                        client.SendChatText("");
                        client.SendChatText("Social page:");
                        meshs = client.Character.SocialMeshLayer.GetMeshs();
                        foreach (AOMeshs am in meshs)
                        {
                            int ov = am.OverrideTexture;
                            int me = am.Mesh;
                            int position = am.Position;
                            int layer = am.Layer;
                            client.SendChatText(position + ":" + me + ":" + ov + ":" + layer);
                        }

                        client.SendChatText("Actual Output:");
                        bool socialonly = ((client.Character.Stats.VisualFlags.Value & 0x40) > 0);
                        bool showsocial = ((client.Character.Stats.VisualFlags.Value & 0x20) > 0);

                        meshs = Misc.MeshLayers.GetMeshs(client.Character, showsocial, socialonly);
                        foreach (AOMeshs am in meshs)
                        {
                            int ov = am.OverrideTexture;
                            int me = am.Mesh;
                            int position = am.Position;
                            int layer = am.Layer;
                            client.SendChatText(position + ":" + me + ":" + ov + ":" + layer);
                        }



                        break;
                    }
                #endregion
                #region ListTimers
                case "listtimers":
                    {
                        lock (client.Character.Timers)
                        {
                            client.SendChatText("--------------------------------------------------");
                            client.SendChatText("Timer Debug output  Startup: " + client.Character.startup.ToString() + " NOW: " + DateTime.Now.ToString());
                            foreach (AOTimers at in client.Character.Timers)
                            {
                                string func = " Function " + at.Function.FunctionType.ToString() + " Args: ";
                                foreach (object d in at.Function.Arguments)
                                {
                                    func = func + d.ToString() + ", ";
                                }
                                func = func.Substring(0, func.Length - 2);

                                client.SendChatText("Strain:" + at.Strain.ToString() + " TI: " + at.Function.TickInterval.ToString() + " TC: " + at.Function.TickCount.ToString() + " NT: " + at.Timestamp.ToString() + func);
                            }
                        }
                        break;
                    }
                case "showstatel":
                    {
                        if (cmdArgs.Length != 1)
                        {
                            client.SendChatText("Usage: /command showstatel ");
                            client.SendChatText("It shows the nearest statel object");
                            break;
                        }
                        client.SendChatText("Looking up for statel in playfield " + client.Character.PlayField.ToString());
                        Statels.Statel o = null;
                        foreach (Statels.Statel s in Statels.Statelppf[client.Character.PlayField])
                        {
                            if (o == null)
                            {
                                o = s;
                            }
                            else
                            {
                                if (AOCoord.distance2D(client.Character.Coordinates, s.Coordinates) < AOCoord.distance2D(client.Character.Coordinates, o.Coordinates))
                                {
                                    o = s;
                                }
                            }
                        }
                        if (o == null)
                        {
                            client.SendChatText("No statel on this playfield... Very odd, where exactly are you???");
                            break;
                        }

                        foreach (Statels.Statel_Event se in o.Events)
                        {
                            client.SendChatText("Event: " + se.EventNumber.ToString() + " # of Functions: " + se.Functions.Count.ToString());
                            foreach (Statels.Statel_Function sf in se.Functions)
                            {
                                string args = "";
                                foreach (string arg in sf.Arguments)
                                {
                                    if (args != "")
                                    {
                                        args = args + ", ";
                                    }
                                    args = args + arg;
                                }
                                string reqs = "";
                                client.SendChatText("    Fn: " + sf.FunctionNumber.ToString() + ", # of Args: " + sf.Arguments.Count.ToString());
                                client.SendChatText("    Args: " + args);
                                foreach (Statels.Statel_Function_Requirement sfr in sf.Requirements)
                                {
                                    string req;
                                    req = "Attr: " + sfr.AttributeNumber.ToString() + " Value: " + sfr.AttributeValue.ToString() + " Target: " + sfr.Target.ToString() + " Op: " + sfr.Operator.ToString();
                                    client.SendChatText("    Req: " + req);
                                }
                            }
                        }

                        break;
                    }
                #endregion
            }
        }
        #region Checks (These are bools to check if Item is already in Placement or if Nano is already uploaded)
        public static bool HasNano(int nanoID, Client m_client)
        {
            bool found = false;
            foreach (AOUploadedNanos au in m_client.Character.UploadedNanos)
            {
                if (au.Nano != nanoID) continue;
                found = true;
                break;
            }
            return found;
        }

        public static bool ItemExists(int Placement, Client m_client)
        {
            return (m_client.Character.getInventoryAt(Placement) != null);
        }
        #endregion
    }
}
